﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using ActiveStory.IO;
using ActiveStory.IO.XmlElementNames;
using System.Windows;
using System.Windows.Media;

namespace ActiveStory.DataManager
{
    public class ActiveStoryProject
    {
        #region Constructors

        /// <summary>
        /// Project Creation Constructor. Does not load or save any files. LoadFile or SaveFile must be called explicitly.
        /// </summary>
        /// <param name="projectFileName">Project filename.</param>
        public ActiveStoryProject(String projectName, String projectFileName, Point defaultCanvasSize, Color defaultCanvasColor)
        {
            _projectFileName = projectFileName;
            _projectName = projectName;
            _pageMetadataList = new SortedPageObservableCollection();
            _pageLookupTable = new Dictionary<int, ActiveStoryPageMetadata>();
            _defaultCanvasSize = defaultCanvasSize;
            DefaultCanvasColor = defaultCanvasColor;
        }
        /// <summary>
        /// Project constructor for use when loading a project. Automatically loads the project.
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="projectFileName"></param>
        /// <param name="pageCounter"></param>
        public ActiveStoryProject(String projectFileName)
        {
            _projectFileName = projectFileName;
            _pageMetadataList = new SortedPageObservableCollection();
            _pageLookupTable = new Dictionary<int, ActiveStoryPageMetadata>();
            _defaultCanvasSize = new Point();
            DefaultCanvasColor = Colors.White;
            LoadFile();
        }
        #endregion
        #region Fields
        /// <summary>
        /// Filename of the project metadata file (full path).
        /// </summary>
        protected string _projectFileName;
        /// <summary>
        /// List of Page Metadata. Contains objects of <typeparamref name="ActiveStoryPageMetadata"/>.
        /// Set to empty list by constructor, loaded by explicitly calling ActiveStoryProject.LoadFile on the project file.
        /// </summary>
        protected SortedPageObservableCollection _pageMetadataList;
        /// <summary>
        /// Lookup table for pages. Page file locations can be looked up by page number. Intended for quick page retrieval
        /// using only page number (ex. from listbox)
        /// </summary>
        protected Dictionary<int, ActiveStoryPageMetadata> _pageLookupTable;
        /// <summary>
        /// The name of the project. Used when assigning names to the files.
        /// </summary>
        protected string _projectName;
        /// <summary>
        /// The counter for numbering pages. Must be incremented by calling incrementPageCounter()
        /// whenever a page is added (by save a page's metadata)
        /// </summary>
        protected int _pageCounter;
        /// <summary>
        /// Defaults size of the canvas x=width, y=height for new pages.
        /// </summary>
        protected Point _defaultCanvasSize;
        #endregion
        #region Properties
        /// <summary>
        /// Filename of the project metadata file (full path).
        /// </summary>
        public String ProjectFileName
        {
            get
            {
                return _projectFileName;
            }
            set
            {
                _projectFileName = value;
            }
        }
        /// <summary>
        /// The path of the project, obtained from the project filename.
        /// All images, xaml files and buttonTransitionMaps are located in this path.
        /// </summary>
        public String ProjectPath
        {
            get
            {
                return Path.GetDirectoryName(_projectFileName);
            }
        }
        /// <summary>
        /// List of Page Metadata. Contains objects of <typeparamref name="ActiveStoryPageMetadata"/>.
        /// Set to empty list by constructor, loaded by explicitly calling ActiveStoryProject.LoadFile on the project file.
        /// </summary>
        public SortedPageObservableCollection PageMetadataList
        {
            get
            {
                return _pageMetadataList;
            }
        }
        /// <summary>
        /// The name of the project. Used when assigning names to the files.
        /// </summary>
        public String ProjectName
        {
            get
            {
                return _projectName;
            }
        }
        /// <summary>
        /// The counter for numbering pages. Must be incremented by calling incrementPageCounter()
        /// whenever a page is added (by save a page's metadata)
        /// </summary>
        public int PageCounter
        {
            get
            {
                return _pageCounter;
            }
        }
        /// <summary>
        /// Lookup table for pages. Page file locations can be looked up by page number. Intended for quick page retrieval
        /// using only page number (ex. from listbox)
        /// </summary>
        public Dictionary<int, ActiveStoryPageMetadata> PageLookupTable
        {
            get
            {
                return _pageLookupTable;
            }
        }
        /// <summary>
        /// Defaults size of the canvas x=width, y=height for new pages.
        /// </summary>
        public Point DefaultCanvasSize
        {
            get
            {
                return _defaultCanvasSize;
            }
            set
            {
                _defaultCanvasSize = value;
            }
        }
        /// <summary>
        /// Default color of the canvas, used for all new pages.
        /// </summary>
        public Color DefaultCanvasColor { get; set; }
        #endregion
        #region Methods
        /// <summary>
        /// Loads a project file from the given file (full path) into the <typeparamref name="ActiveStoryProject"/>.
        /// </summary>
        /// <param name="projectFileName">Full path to project file.</param>
        /// <returns></returns>
        protected void LoadFile()
        {
            XmlActiveStoryProjectReader xaspr = new XmlActiveStoryProjectReader();
            string[] result = xaspr.ParseFile(ProjectFileName);
            _projectName = result[0];
            _pageCounter = int.Parse(result[1]);
            XmlMapFileReader<int, string> xmfr = new XmlMapFileReader<int, string>();
            Dictionary<int,string> table =(Dictionary<int,string>) xmfr.ParseFile(FileManager.GetAbsolutePath(result[2]), PageLookupFileXmlNames.RootElement, PageLookupFileXmlNames.ItemElement, PageLookupFileXmlNames.PageNumberElement, PageLookupFileXmlNames.PageFilePathElement);
            _defaultCanvasSize = new Point(double.Parse(result[3]), double.Parse(result[4]));
            DefaultCanvasColor = (Color) ColorConverter.ConvertFromString((String)result[5]);
            foreach (KeyValuePair<int,string> item in table)
            {
                AddPage(item.Key, item.Value);
            }
        }
        /// <summary>
        /// Saves the project to a project file (<value>ActiveStoryApplication.ProjectFileExtension</value>)
        /// </summary>
        /// <param name="projectObject">The project object to be saved.</param>
        /// <param name="projectFileName">The filename to save the project as.</param>
        public void SaveFile()
        {
            XmlMapFileWriter<int, string> xmfw = new XmlMapFileWriter<int, string>();
            Dictionary<int, string> pageFileTable = new Dictionary<int, string>();
            foreach (KeyValuePair<int,ActiveStoryPageMetadata> item in PageLookupTable)
            {
                pageFileTable.Add(item.Key, item.Value.PageFileLocation);
            }
            xmfw.SaveFile(FileManager.GetAbsolutePath(FileManager.CreatePageLookupTableFileName(ProjectName)), pageFileTable, PageLookupFileXmlNames.RootElement, PageLookupFileXmlNames.ItemElement, PageLookupFileXmlNames.PageNumberElement, PageLookupFileXmlNames.PageFilePathElement);
            XmlActiveStoryProjectWriter xaspw = new XmlActiveStoryProjectWriter();
            xaspw.SaveFile(ProjectFileName, ProjectName, PageCounter, FileManager.CreatePageLookupTableFileName(ProjectName), DefaultCanvasSize, DefaultCanvasColor);
        }

        public void AddPage(int pageNumber, string pageFileName)
        {
            ActiveStoryPageMetadata metadata = ActiveStoryPageMetadata.LoadMetadata(pageFileName);
            if (_pageLookupTable.ContainsKey(pageNumber))
            {
                int index = _pageMetadataList.IndexOf(_pageLookupTable[pageNumber]);
                _pageMetadataList[index] = metadata;
                _pageLookupTable[pageNumber] = metadata;
            }
            else
            {
                _pageLookupTable.Add(pageNumber, metadata);
                _pageMetadataList.Add(metadata);
            }
        }

        public void RemovePage(int pageNumber)
        {
            if (!_pageLookupTable.ContainsKey(pageNumber))
                return;
            _pageMetadataList.Remove(_pageLookupTable[pageNumber]);
            _pageLookupTable.Remove(pageNumber);
        }

        /// <summary>
        /// Increments the counter for numbering pages. Must be incremented explicitly
        /// whenever a page is added (by save a page's metadata)
        /// </summary>
        public void IncrementPageCounter()
        {
            _pageCounter++;
        }
        #endregion
    }
}
